package me.zhengjie.modules.sync.processing.forkjoin;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.qiaofang.applet.common.constant.SyncTypeEnum;
import com.qiaofang.applet.constants.SyncProcessingStatusConstants;
import com.qiaofang.applet.service.property.domain.*;
import com.qiaofang.applet.service.property.service.DataProcessingErrorLogService;
import com.qiaofang.applet.service.property.service.PropertyDataHandleService;
import com.qiaofang.applet.service.property.service.PropertyService;
import com.qiaofang.applet.service.property.service.SyncDataQueueService;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.utils.ImageUtil;
import me.zhengjie.utils.SpringContextHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.RecursiveAction;

@Slf4j
public class PropertyForkJoinProcessingTask extends RecursiveAction {
    public static final int PAGE_SIZE = 20;
    //分割页
    private static final int segmentation = 10;
    //开始页
    private int fromPage;
    //结束页
    private int toPage;

    private SyncDataQueueService syncDataQueueService;

    private DataProcessingErrorLogService dataProcessingErrorLogService;

    private PropertyService propertyService;

    private PropertyDataHandleService propertyDataHandleService;

    {
        syncDataQueueService= SpringContextHolder.getBean(SyncDataQueueService.class);
        dataProcessingErrorLogService= SpringContextHolder.getBean(DataProcessingErrorLogService.class);
        propertyService= SpringContextHolder.getBean(PropertyService.class);
        propertyDataHandleService= SpringContextHolder.getBean(PropertyDataHandleService.class);
    }

    public PropertyForkJoinProcessingTask(int fromPage, int toPage){
        this.fromPage=fromPage;
        this.toPage=toPage;
    }

    @Override
    protected void compute() {
        if((toPage - fromPage)<segmentation ){
            computeDirectly();
        }else{
            int mid = (fromPage+toPage)/2;
            PropertyForkJoinProcessingTask left =  new PropertyForkJoinProcessingTask(fromPage,mid);
            PropertyForkJoinProcessingTask right = new PropertyForkJoinProcessingTask(mid+1,toPage);
            invokeAll(left,right);
        }
    }

    protected void computeDirectly() {
        for(int i = this.fromPage;i<=this.toPage;i++){
            Page<SyncDataQueue> page=syncDataQueueService.findSyncDataQueuePage(SyncProcessingStatusConstants.UN_HANDLE, SyncTypeEnum.SALE_AND_RENT.getSyncType(),i,PAGE_SIZE);
            page.forEach(item->{
                processingRow(item);
            });
        }
    }

    private void processingRow(SyncDataQueue item){
        try {
            processing(item);
            item.setProcessingStatus(SyncProcessingStatusConstants.HANDLED);
        } catch (Exception e) {
            log.error("processingRow error",e);
            item.setProcessingStatus(SyncProcessingStatusConstants.HANDLE_FAIL);
            syncDataQueueService.save(item);
        }
        syncDataQueueService.save(item);
    }

    protected void saveErrorLog(String body,String errorMsg,SyncDataQueue queue){
        DataProcessingErrorLog errorLog=new DataProcessingErrorLog();
        errorLog.setDataType(SyncTypeEnum.SALE_AND_RENT.getSyncType());
        errorLog.setBody(body);
        errorLog.setErrorMsg(errorMsg);
        errorLog.setCreateTime(new Date());
        errorLog.setUpdateTime(new Date());
        errorLog.setCompanyUuid(queue.getCompanyUuid());
        errorLog.setCorporationCode(queue.getCorporationCode());
        errorLog.setCityCode(queue.getCityCode());
        dataProcessingErrorLogService.save(errorLog);
    }



    public void processing(SyncDataQueue syncDataQueue) {
        String batchContent=syncDataQueue.getBatchContent();
        List<Property> list= JSON.parseArray(batchContent,Property.class);
        if(null==list){
            log.info("processing property is null");
            return;
        }
        list.stream().forEach(item->{
            saveProperty(item,syncDataQueue);
        });
    }

    private void saveProperty(Property item,SyncDataQueue syncDataQueue){
        String propertyUniqueUuid=syncDataQueue.getCompanyUuid()+"_"+item.getPropertyUuid();
        Property property= propertyService.findByPropertyUniqueUuid(propertyUniqueUuid);
        if(!Objects.isNull(item.getDeleted()) && item.getDeleted() && !Objects.isNull(property)){
            propertyService.deleteById(property.getId());
            return;
        }
        if(Objects.isNull(property)){
            property=new Property();
            property.setRecommend(false);
            property.setUpDownFlag("上架");
        }
        //复制属性
        String[] ignoreProperties=new String[] { "id","recommend", "upDownFlag","updateBy","createTime","updateTime"};
        BeanUtils.copyProperties(item,property,ignoreProperties);
        //计算楼层范围（高/中/低）字段，规则为实际楼层低于总楼层1/3为低，高于总楼层2/3为高，其余为中层
        property.setFloorRange(getFloorRange(property.getFloor(),property.getTotalFloor()));
        property.setCompanyUuid(syncDataQueue.getCompanyUuid());
        property.setCityCode(syncDataQueue.getCityCode());
        property.setCorporationCode(syncDataQueue.getCorporationCode());
        property.setUpdateTime(new Date());
        //房源描述
        if(!CollectionUtils.isEmpty(item.getPropertyExplainList())){
            PropertyExplain propertyExplainVO = item.getPropertyExplainList().get(0);
            property.setPropertyExplain(propertyExplainVO.getContent());
        }
        processingPhoto(property);
        //上下架
        setUpDownFlag(property);
        property.setPropertyUniqueUuid(propertyUniqueUuid);
        try {
            propertyDataHandleService.initPropertyRedundanceField(property);
            property.setRelationUpdate(false);
            propertyService.save(property);
        } catch (Exception e) {
            log.error("saveProperty error",e);
            //记录错误日志
            this.saveErrorLog(JSON.toJSONString(property),e.getMessage(),syncDataQueue);
        }
    }

    //上架规则
    private void setUpDownFlag(Property property){
        //图片大于5张上架 && 状态是有效
        List<PropertyPhoto>  photoList= property.getPhotoList();
        String upDownFlag="下架";
        if ((!CollectionUtils.isEmpty(photoList) && photoList.size()>5) && "有效".equals(property.getTradeStatus())){
            upDownFlag="上架";
        }
        property.setUpDownFlag(upDownFlag);
    }

    //处理图片相关
    private void processingPhoto(Property property){
        String domainUrl= ImageUtil.HTTP+ImageUtil.IMAGE_URL+"/";
        List<PropertyPhoto>  photoList= property.getPhotoList();
        if(null==photoList) return;
        List<String> replaceList=new ArrayList<>();
        for(PropertyPhoto propertyPhoto : photoList){
            if(StringUtils.isEmpty(propertyPhoto.getPhotoURL())){
                continue;
            }
            String replaceUrl =domainUrl+propertyPhoto.getPhotoURL();
            replaceList.add(replaceUrl);
        }
        if(null==replaceList)return;
        //设置图片集合
        property.setImageUrls(replaceList);
        //设置首图
        property.setMainImageUrl(minSort(domainUrl,photoList));
    }

    private static String minSort(String domainUrl, List<PropertyPhoto> vo){
        if(null == vo || vo.isEmpty()){
            return  "";
        }
        Collections.sort(vo,new Comparator<PropertyPhoto>() {
            @Override
            public int compare(PropertyPhoto v1,PropertyPhoto v2){
                if(null==v1.getPhotoIndex() || null==v2.getPhotoIndex()){
                    return 0;
                }
                if(v1.getPhotoIndex() > v2.getPhotoIndex()){
                    return 1;
                }else if(v1.getPhotoIndex() < v2.getPhotoIndex()){
                    return -1;
                }else{
                    return 0;
                }
            }
        });
        return domainUrl + vo.get(0).getPhotoURL();
    }

    private String getFloorRange(String floor,Integer totalFloor){
        if(StringUtils.isEmpty(floor) || Objects.isNull(totalFloor)){
            return "";
        }
        if(!NumberUtil.isInteger(floor)){
            return "";
        }
        if((Integer.valueOf(floor).intValue()*3)<(totalFloor.intValue()*1)){
            return "底层";
        }else if((Integer.valueOf(floor).intValue()*3)>(totalFloor.intValue()*2)){
            return "高层";
        }else{
            return "中层";
        }

    }

}
